﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Jayden.Dll.Cards.Poker;
using Jayden.Dll.Core;
using System.IO;
using Jayden.Dll.Cards.Poker.PokerStars;
using Jayden.Dll.Core.Persistence;
using Jayden.Dll.Cards;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;

namespace Jayden.Windows.PokerWatcher
{
	public partial class PokerWatcherForm : Form
	{
		public Configuration Configuration { get; set; }
		public UnitOfWork UnitOfWork { get; set; }

		private Dictionary<string, TexasHoldemPlayerStatistics> SessionStatistics = new Dictionary<string, TexasHoldemPlayerStatistics>();
		private Dictionary<string, TexasHoldemPlayerStatistics> OverallStatistics = new Dictionary<string, TexasHoldemPlayerStatistics>();

		public PokerWatcherForm()
		{
			InitializeComponent();

			lvStatistics.Columns.Add("PlayerName", 100);
			lvStatistics.Columns.Add("Balance", 80);
			lvStatistics.Columns.Add("Hands");
			lvStatistics.Columns.Add("VP$IP");
			lvStatistics.Columns.Add("PFR", 100);
			lvStatistics.Columns.Add("CBet");
			lvStatistics.Columns.Add("3Bet");
			lvStatistics.Columns.Add("4Bet");
			lvStatistics.Columns.Add("W$WSF");
			lvStatistics.Columns.Add("WTSD");
			lvStatistics.Columns.Add("W$SD");
			lvStatistics.Columns.Add("SDWSP");
			lvStatistics.Columns.Add("Won");
			lvStatistics.Columns.Add("Hands Played", 300);
			lvStatistics.Columns.Add("Hands Range (Sklansky)", 300);
			lvStatistics.Columns.Add("PFR Hands Range (Sklansky)", 300);
			lvStatistics.Columns.Add("3Bet Hands Range (Sklansky)", 300);

			string handHistoryPath = @"C:\Users\Jonathan\AppData\Local\PokerStars.BE\HandHistory\jonv11\";
			string handFilter = "*No Limit Hold'em.txt";
			FileSystemWatcher watcher = new FileSystemWatcher(handHistoryPath, handFilter);
			//watcher.NotifyFilter = NotifyFilters.LastWrite;
			watcher.Changed += new FileSystemEventHandler(FileChanged);
			watcher.Created += new FileSystemEventHandler(FileChanged);
			watcher.EnableRaisingEvents = true;

			tbFilter.TextChanged += new EventHandler(tbFilter_TextChanged);
			/*
			PokerTableOverlay overlay = new PokerTableOverlay();
			overlay.Show();
			*/
		}

		private string m_Filter = null;
		private void tbFilter_TextChanged(object sender, EventArgs e)
		{
			m_Filter = tbFilter.Text;
			ApplyFilter();
		}

		private Dictionary<string, PokerFileWatcher> LastWriteTimes = new Dictionary<string, PokerFileWatcher>();
		public class PokerFileWatcher
		{
			public string FullPath;
			public DateTime LastWriteTime;
			public int LastHandCount;
		}

		private void FileChanged(object sender, FileSystemEventArgs e)
		{
			try
			{
				lock (SessionStatistics)
				{
					string[] lines = File.ReadAllLines(e.FullPath);
					DateTime lastWriteTime = File.GetLastWriteTime(e.FullPath);
					PokerFileWatcher fileWatcher = null;
					lock (LastWriteTimes)
					{
						if (!LastWriteTimes.TryGetValue(e.FullPath, out fileWatcher))
						{
							fileWatcher = new PokerFileWatcher();
							fileWatcher.FullPath = e.FullPath;
							fileWatcher.LastHandCount = 0;
							fileWatcher.LastWriteTime = DateTime.MinValue;
							LastWriteTimes.Add(e.FullPath, fileWatcher);
						}
					}
					if (lastWriteTime.CompareTo(fileWatcher.LastWriteTime) > 0)
					{
						try
						{
							fileWatcher.LastWriteTime = lastWriteTime;
							List<TexasHoldemHandSummaryLegacy> s = new List<TexasHoldemHandSummaryLegacy>(HistoryReader.Read(lines));
							if (s.Count > fileWatcher.LastHandCount)
							{
								for (int c = fileWatcher.LastHandCount; c < s.Count; c++)
								{
									s[c].ComputeStatistics(UnitOfWork, SessionStatistics, false, false);
									s[c].ComputeStatistics(UnitOfWork, OverallStatistics, false, true);
								}
								fileWatcher.LastHandCount = s.Count;
							}
						}
						catch (Exception exc)
						{
						}
					}

					lvStatistics.Invoke((MethodInvoker) delegate()
					{
						lvStatistics.Items.Clear();
						List<TexasHoldemPlayerStatistics> sorted = new List<TexasHoldemPlayerStatistics>(cbOverallData.Checked ? OverallStatistics.Values : SessionStatistics.Values);
						sorted.Sort(Program.LastChangesStats);

						foreach (TexasHoldemPlayerStatistics stat in sorted)
							AddStatistics(stat);
						ApplyFilter();
					});
				}
			}
			catch
			{
			}
		}

		public void ApplyFilter()
		{
			Regex regex = null;
			if (!string.IsNullOrWhiteSpace(m_Filter))
			{
				try
				{
					regex = new Regex(m_Filter);
				}
				catch
				{
					regex = null;
				}
			}
			foreach (ListViewItem item in lvStatistics.Items)
			{
				string text = item.SubItems[0].Text;
				if (regex != null && regex.IsMatch(text))
					item.Font = new Font(item.Font, FontStyle.Bold);
				else
					item.Font = new Font(item.Font, FontStyle.Regular);
			}
		}

		public void AddStatistics(TexasHoldemPlayerStatistics statistic, bool doNotGray = false)
		{
			TimeSpan lastSeen = DateTime.Now.Subtract(statistic.LastChanges);
			double vpip = (statistic.VPIP * 100.0 / statistic.HandCount);
			double pfr = (statistic.PFR * 100.0 / statistic.HandCount);
			double wwsf = (statistic.WWSF * 100.0 / statistic.SF);
			double wsd = (statistic.WSD * 100.0 / statistic.WTSD);
			double sdwsf = (statistic.WTSD * 100.0 / statistic.SF);
			ListViewItem item = new ListViewItem(new string[]
			{
				statistic.PlayerName,
				(statistic.PlayerBalance / 100.0).ToString("0.00") + " " + statistic.Currency,
				statistic.HandCount.ToString(),
				vpip.ToString("0.00") + " %",
				pfr.ToString("0.00") + " %" + " (" + (pfr * 100.0 / vpip).ToString("0.00") + " %)",
				(statistic.CBetFlop * 100.0 / statistic.PFR).ToString("0.00") + " %",
				(statistic.Bet3 * 100.0 / statistic.HandCount).ToString("0.00") + " %",
				(statistic.Bet4 * 100.0 / statistic.HandCount).ToString("0.00") + " %",
				wwsf.ToString("0.00") + " %",
				(statistic.WTSD * 100.0 / statistic.HandCount).ToString("0.00") + " %",
				wsd.ToString("0.00") + " %",
				sdwsf.ToString("0.00") + " %",
				(statistic.Won * 100.0 / statistic.HandCount).ToString("0.00") + " %",
				statistic.HandRangeList.Count == 0 ? string.Empty : (statistic.HandRangeList.Percentage * 100).ToString("0.00") + " % : " + statistic.HandRange,
				Program.SklanskyLevels.GetHandRange((statistic.VPIP * 1.0 / statistic.HandCount)).ToString(),
				Program.SklanskyLevels.GetHandRange((statistic.PFR * 1.0 / statistic.HandCount)).ToString(),
				Program.SklanskyLevels.GetHandRange((statistic.Bet3 * 1.0 / statistic.HandCount)).ToString()
			});
			item.UseItemStyleForSubItems = false;
			lvStatistics.Items.Add(item);

			if (!doNotGray && lastSeen.TotalMinutes > 10)
				item.ForeColor = Color.Gray;

			if(statistic.PlayerBalance < 0)
				item.SubItems[1].ForeColor = Color.Red;
			else if (statistic.PlayerBalance > 0)
				item.SubItems[1].ForeColor = Color.DarkGreen;

			if (statistic.HandCount >= 250)
				item.SubItems[2].BackColor = Color.LightGreen;
			if (statistic.HandCount < 250)
				item.SubItems[2].BackColor = Color.Yellow;
			if (statistic.HandCount < 100)
				item.SubItems[2].BackColor = Color.Orange;
			if (statistic.HandCount < 50)
				item.SubItems[2].BackColor = Color.Red;

			//http://www.thepokerbank.com/articles/software/vpip/
			if (vpip < 40) // loose
				item.SubItems[3].BackColor = Color.LightYellow;
			if (vpip < 32) // semi-loose
				item.SubItems[3].BackColor = Color.Yellow;
			if (vpip < 23) // tight
				item.SubItems[3].BackColor = Color.Orange;
			if(vpip < 14) // very tight
				item.SubItems[3].BackColor = Color.Red;

			if(pfr < vpip * 0.3)
				item.SubItems[4].BackColor = Color.LightGreen;
			else if(pfr < vpip * 0.7)
				item.SubItems[4].BackColor = Color.Yellow;
			else
				item.SubItems[4].BackColor = Color.Orange;

			if (wsd < 40)
				item.SubItems[10].BackColor = Color.LightGreen;
			else if(wsd < 48)
				item.SubItems[10].BackColor = Color.Yellow;
			else if(wsd < 54)
				item.SubItems[10].BackColor = Color.Orange;
			else
				item.SubItems[10].BackColor = Color.Red;

			if(sdwsf < 20)
				item.SubItems[11].BackColor = Color.Red;
			else if(sdwsf <30)
				item.SubItems[11].BackColor = Color.Orange;
			else
				item.SubItems[11].BackColor = Color.Green;
		}

	}
}
